#include "StdAfx.h"
#include "GameCharacter.h"
#include <iostream>
using namespace std;
//////////////////////////////////////////////////////////////////////////
//
//								CCharacterPos
//
//////////////////////////////////////////////////////////////////////////

void CCharacterPos::Offset( int nOffsetX, int nOffsetY )
{
	m_uXIndex += nOffsetX;
	m_uYIndex += nOffsetY;
}

CCharacterPos::CCharacterPos( UINT uXIndex /*= 0*/, UINT uYIndex /*= 0*/, UINT uXLength /*= 0*/, UINT uYLength /*= 0*/ )
{
	m_uXIndex = uXIndex;	
	m_uYIndex = uYIndex;	
	m_uXLength = uXLength;
	m_uYLength = uYLength;
}

// void CCharacterPos::Offset( int nOffsetX, int nOffsetY )
// {
// 	m_uLeft += nOffsetX;
// 	m_uRight += nOffsetX;
// 	m_uTop += nOffsetY;
// 	m_uBottom += nOffsetY;
// }

//////////////////////////////////////////////////////////////////////////
//
//								CGameCharacter
//
//////////////////////////////////////////////////////////////////////////

CGameCharacter::CGameCharacter( UINT uID, CCharacterPos pos )
{
	m_uCharacterID = uID;
	m_CharacterPos = pos;
	const wchar_t *pContents = FormatLogContents(L"New Character : %u Created", m_uCharacterID);
	WRITELOGW(pContents, ll_Debug, false);
}


CGameCharacter::~CGameCharacter(void)
{
	const wchar_t *pContents = FormatLogContents(L" Character : %u Destroyed", m_uCharacterID);
	WRITELOGW(pContents, ll_Debug, false);
}

BOOL CGameCharacter::MoveSteps( DWORD dwMoveFlag, int iSteps )
{
	if (dwMoveFlag == MF_MOVE_HORZ)
	{
		m_CharacterPos.Offset(iSteps, 0);
	}
	else if (dwMoveFlag == MF_MOVE_VERT)
	{
		m_CharacterPos.Offset(0, iSteps);
	}
	else
	{
		return FALSE;
	}
	const wchar_t *pContents = FormatLogContents(L" Character : %u Move Director = %u, steps = %d", m_uCharacterID, dwMoveFlag, iSteps);
	WRITELOGW(pContents, ll_Debug, false);
	return TRUE;
}

BOOL CGameCharacter::GetCurrentPos( CCharacterPos & curPos )
{
	curPos = m_CharacterPos;
	return TRUE;
}

//////////////////////////////////////////////////////////////////////////
//
//								ChessBoard
//
//////////////////////////////////////////////////////////////////////////

CChessBoard::CChessBoard()
{
	m_uChessBoardWidth = 0;
	m_uChessBoardHeight = 0;
	m_pChessBoard = NULL;
}

CChessBoard::~CChessBoard()
{
	FreeData();
}

BOOL CChessBoard::InitBoard( UINT nBoardWidth, UINT nBoardHeight )
{
	if (m_pChessBoard)
	{
		FreeData();
	}
	if (AllocData(nBoardWidth, nBoardHeight) && m_pChessBoard)
	{
		return TRUE;
	}
	return FALSE;
}

BOOL CChessBoard::DestoryBoard()
{
	FreeData();
	return TRUE;
}

BOOL CChessBoard::SetBoardValue( UINT nIndexX, UINT nIndexY, USHORT uValue )
{
	if (m_pChessBoard)
	{
		if (nIndexX >= m_uChessBoardWidth || nIndexY >= m_uChessBoardHeight)//error paramter
		{
			return FALSE;
		}
		m_pChessBoard[nIndexY][nIndexX] = uValue;
		return TRUE;
	}
	return FALSE;
}

BOOL CChessBoard::GetBoardValue( UINT nIndexX, UINT nIndexY, USHORT &uValue )
{
	if (m_pChessBoard)
	{
		if (nIndexX >= m_uChessBoardWidth ||nIndexY >= m_uChessBoardHeight)//error paramter
		{
			return FALSE;
		}
		uValue = m_pChessBoard[nIndexY][nIndexX];
		return TRUE;
	}
	return FALSE;
}

BOOL CChessBoard::SetBoardValues( const UINT *pIndexXArray, const UINT *pIndexYArray, const USHORT *pValueArray, const UINT nCount )
{
	if (m_pChessBoard)
	{
		if (!pIndexXArray || !pIndexYArray || !pValueArray || nCount > m_uChessBoardWidth*m_uChessBoardHeight)//error paramter
		{
			return FALSE;
		}
		for (int i = 0; i < nCount; ++i)
		{
			if (!SetBoardValue(pIndexXArray[i], pIndexYArray[i], pValueArray[i]))
			{
				return FALSE;
			}
		}
		return TRUE;
	}
	return FALSE;
}

BOOL CChessBoard::GetBoardValues( const UINT *pIndexXArray, const UINT *pIndexYArray, USHORT *pValueArray, const UINT nCount )
{
	if (m_pChessBoard)
	{
		if (!pIndexXArray || !pIndexYArray || !pValueArray || nCount > m_uChessBoardWidth*m_uChessBoardHeight)//error paramter
		{
			return FALSE;
		}
		for (int i = 0; i < nCount; ++i)
		{
			if (!GetBoardValue(pIndexXArray[i], pIndexYArray[i], pValueArray[i]))
			{
				return FALSE;
			}
		}
		return TRUE;
	}
	return FALSE;
}

BOOL CChessBoard::CheckOccupied( UINT nIndexX, UINT nIndexY )
{
	if (nIndexX >= m_uChessBoardWidth || nIndexY >= m_uChessBoardHeight)//error paramter
	{
		return TRUE;
	}
	return !(!m_pChessBoard[nIndexY][nIndexX]);
}

BOOL CChessBoard::CheckBoundary( UINT nIndexX, UINT nIndexY )
{
	if (nIndexX >= m_uChessBoardWidth || nIndexY >= m_uChessBoardHeight)//error paramter
	{
		return TRUE;
	}
	return (nIndexX == 0 || nIndexX == m_uChessBoardWidth-1 || nIndexY == 0 || nIndexY == m_uChessBoardHeight-1);
}

BOOL CChessBoard::CheckOccupiedEx( UINT nIndexX, UINT nIndexY, BOOL &bOccupied )
{
	if (nIndexX >= m_uChessBoardWidth || nIndexY >= m_uChessBoardHeight)//error paramter
	{
		return FALSE;
	}
	bOccupied = !(!m_pChessBoard[nIndexY][nIndexX]);
	return TRUE;
}

BOOL CChessBoard::CheckBoundaryEx( UINT nIndexX, UINT nIndexY, BOOL &bBoundary )
{
	if (nIndexX >= m_uChessBoardWidth || nIndexY >= m_uChessBoardHeight)//error paramter
	{
		return FALSE;
	}
	bBoundary = (nIndexX == 0 || nIndexX == m_uChessBoardWidth-1 || nIndexY == 0 || nIndexY == m_uChessBoardHeight-1);
	return TRUE;
}

BOOL CChessBoard::AllocData( UINT &nBoardWidth, UINT &nBoardHeight )
{
	if (nBoardWidth == 0 || nBoardHeight == 0)
	{
		return FALSE;
	}
	if (m_pChessBoard)
	{
		FreeData();
	}
	m_uChessBoardWidth = nBoardWidth;
	m_uChessBoardHeight = nBoardHeight;
	m_pChessBoard = new USHORT*[m_uChessBoardHeight];
	if (!m_pChessBoard)
	{
		return FALSE;
	}
	memset(m_pChessBoard, 0, m_uChessBoardHeight*sizeof(USHORT));
	for (int i = 0; i < m_uChessBoardHeight; ++i)
	{
		m_pChessBoard[i] = new USHORT[m_uChessBoardWidth];
		if (!m_pChessBoard[i])
		{
			FreeData();
			return FALSE;
		}
		memset(m_pChessBoard[i], 0 , m_uChessBoardWidth*sizeof(USHORT));
	}
	return TRUE;
}

BOOL CChessBoard::FreeData()
{
	if (m_pChessBoard)
	{
		for (int i = 0; i < m_uChessBoardHeight; ++i)
		{
			if (m_pChessBoard[i])
			{
				delete []m_pChessBoard[i];
			}
		}
		delete []m_pChessBoard;
		m_pChessBoard = NULL;
	}
	m_uChessBoardWidth = 0;
	m_uChessBoardHeight = 0;
	return TRUE;
}

void CChessBoard::PrintChessBoard()
{
	if (m_pChessBoard)
	{
		for (int i = 0; i < m_uChessBoardHeight; ++i)
		{
			if (m_pChessBoard[i])
			{
				for (int j = 0; j < m_uChessBoardWidth; ++j)
				{
					cout<<m_pChessBoard[i][j]<<' ';
				}
				cout<<endl;
			}
		}
	}
}

//////////////////////////////////////////////////////////////////////////
//
//								CPlayGame
//
//////////////////////////////////////////////////////////////////////////

CPlayGame::CPlayGame()
{
// 	m_pGamers = NULL;
	m_pChesseBoard = NULL;
	m_gamerList.clear();
	m_uGameState = GSF_NOTREADY;
}

CPlayGame::~CPlayGame()
{
	Release();
}

BOOL CPlayGame::InitGame( UINT nBoardWidth, UINT nBoardHeight )
{
	BOOL bInitRet = FALSE;
	m_gamerList.clear();
	if (m_pChesseBoard)
	{
		m_pChesseBoard->DestoryBoard();
	}
	else
	{
		m_pChesseBoard = new CChessBoard();
	}
	if (m_pChesseBoard)
	{
		bInitRet = m_pChesseBoard->InitBoard(nBoardWidth, nBoardHeight);
	}
	if (bInitRet)
	{
		m_uGameState = GSF_READY;
	}
	return bInitRet;;
}

BOOL CPlayGame::AddGamer( UINT uXIndex, UINT uYIndex, UINT uXLength, UINT uYLength, UINT &uGamerID )
{
	if (!(m_uGameState & GSF_READY))
	{
		return FALSE;
	}
	UINT uWidth = m_pChesseBoard->GetBoardWidth();
	UINT uHeight = m_pChesseBoard->GetBoardHeight();
	if (uXIndex < 0 || (uXLength+uXIndex > uWidth) || uYIndex < 0 || (uYIndex+uYLength > uHeight))
	{
		return FALSE;
	}
	CGameCharacter *pNewCharacter = new CGameCharacter(m_gamerList.size(), CCharacterPos(uXIndex, uYIndex, uXLength, uYLength));
	if (pNewCharacter)
	{
		m_gamerList.push_back(pNewCharacter);
		uGamerID = pNewCharacter->GetCharacterID();
		for (int i = uXIndex; i < uXIndex+uXLength; ++i)
		{
			for (int j = uYIndex; j < uYIndex+uYLength; ++j)
			{
				m_pChesseBoard->SetBoardValue(i, j, 1);
			}
		}
		return TRUE;
	}
	return FALSE;
}

BOOL CPlayGame::MoveGamer( UINT uGamerID, DWORD dwMoveFlag, int iSteps )
{
	if (!(m_uGameState & GSF_STARTED))
	{
		return FALSE;
	}
	if (uGamerID >= m_gamerList.size())
	{
		return FALSE;
	}
	if (CheckGamerCanMove(uGamerID, dwMoveFlag, iSteps))
	{
		MoveGamerInteral(uGamerID, dwMoveFlag, iSteps);
		return TRUE;
	}
	return FALSE;
}

void CPlayGame::MoveGamerInteral( UINT uGamerID, DWORD dwMoveFlag, int iSteps )
{
	CGameCharacter *pCharacter = m_gamerList[uGamerID];
	if (pCharacter)
	{
		ChangeGamerValue(uGamerID, 0);
		PrintBoard();
		pCharacter->MoveSteps(dwMoveFlag, iSteps);
		ChangeGamerValue(uGamerID, 1);
	}
}

BOOL CPlayGame::CheckGamerCanMove( UINT uGamerID, DWORD dwMoveFlag, int iSteps )
{
// 	if (!(m_uGameState & GSF_STARTED))
// 	{
// 		return FALSE;
// 	}
// 	if (uGamerID >= m_gamerList.size())
// 	{
// 		return FALSE;
// 	}
	UINT uXIndex;
	UINT uYIndex;
	UINT uXLength;
	UINT uYLength;
	if (!GetGamerInfo(uGamerID, uXIndex, uYIndex, uXLength, uYLength))
	{
		return FALSE;
	}
	if (iSteps == 0)
	{
		return TRUE;
	}

	UINT uWidth = m_pChesseBoard->GetBoardWidth();
	UINT uHeight = m_pChesseBoard->GetBoardHeight();
	UINT uXStart = 0;
	UINT uXEnd = 0;
	UINT uYStart = 0;
	UINT uYEnd = 0;
	if (dwMoveFlag == MF_MOVE_HORZ)
	{
		if ((uXIndex+iSteps < 0) || (uXIndex+uXLength+iSteps > uWidth))
		{
			return FALSE;
		}
		if (iSteps > 0)
		{
			uXStart = uXIndex+uXLength;
			uXEnd = uXStart+iSteps-1;
		}
		else
		{
			uXEnd = uXIndex-1;
			uXStart = uXIndex+iSteps;
		}
	}
	else if (dwMoveFlag == MF_MOVE_VERT)
	{
		if ((uYIndex+iSteps < 0) || (uYIndex+uYLength+iSteps > uHeight))
		{
			return FALSE;
		}
		if (iSteps > 0)
		{
			uYStart = uYIndex+uYLength;
			uYEnd = uYStart+iSteps-1;
		}
		else
		{
			uYEnd = uYIndex-1;
			uYStart = uYIndex+iSteps;
		}
	}
	return CheckRegionEmpty(uXStart, uXEnd, uYStart, uYEnd);
}

BOOL CPlayGame::CheckRegionEmpty(UINT uXStart, UINT uXEnd, UINT uYStart, UINT uYEnd)
{
	for (int i = uXStart; i <= uXEnd; ++i)
	{
		for (int j = uYStart; j <= uYEnd; ++j)
		{
			if (m_pChesseBoard->CheckOccupied(i, j))
			{
				return FALSE;
			}
		}
	}
	return TRUE;
}
BOOL CPlayGame::Release()
{
// 	if (m_pGamers)
// 	{
// 		delete m_pGamers;
// 		m_pGamers = NULL;
// 	}
	int nGamersCount = m_gamerList.size();
	for (int i = 0; i < nGamersCount; ++i)
	{
		if (m_gamerList[i])
		{
			delete m_gamerList[i];
			m_gamerList[i] = NULL;
		}
	}
	m_gamerList.clear();
	if (m_pChesseBoard)
	{
		m_pChesseBoard->DestoryBoard();
		delete m_pChesseBoard;
		m_pChesseBoard = NULL;
	}
	return TRUE;
}

BOOL CPlayGame::GetGamerInfo( UINT uGamerID, UINT &uXIndex, UINT &uYIndex, UINT &uXLength, UINT &uYLength )
{
	if (!(m_uGameState & GSF_STARTED))
	{
		return FALSE;
	}
	if (uGamerID >= m_gamerList.size())
	{
		return FALSE;
	}
	CGameCharacter *pCharacter = m_gamerList[uGamerID];
	if (!pCharacter)
	{
		return FALSE;
	}
	CCharacterPos pos;
	pCharacter->GetCurrentPos(pos);
	uXIndex = pos.m_uXIndex;
	uYIndex = pos.m_uYIndex;
	uXLength = pos.m_uXLength;
	uYLength = pos.m_uYLength;
	return TRUE;
}

void CPlayGame::ChangeGamerValue( UINT uGamerID, USHORT uValue )
{
	UINT uXIndex;
	UINT uYIndex;
	UINT uXLength;
	UINT uYLength;
	if (GetGamerInfo(uGamerID, uXIndex, uYIndex, uXLength, uYLength))
	{
		for (int i = uXIndex; i < uXIndex+uXLength; ++i)
		{
			for (int j = uYIndex; j < uYIndex+uYLength; ++j)
			{
				m_pChesseBoard->SetBoardValue(i, j, uValue);
			}
		}
	}
}

BOOL CPlayGame::StartGame()
{
	m_uGameState = GSF_STARTED;
	return TRUE;
}

BOOL CPlayGame::EndGame()
{
	m_uGameState = GSF_GAMEOVER;
	return TRUE;
}
